// Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import UIKit
import MaterialComponents.MaterialAnimationTiming
import MaterialComponents.MaterialTypography

struct Constants {
   struct AnimationTime {
      static let interval: Double = 1.0
      static let delay: Double = 0.5
   }
   struct Sizes {
      static let topMargin: CGFloat = 16.0
      static let leftGutter: CGFloat = 16.0
      static let textOffset: CGFloat = 16.0
      static let circleSize: CGSize = CGSize(width: 48.0, height: 48.0)
   }
}

class AnimationTimingSwiftExampleViewController: UIViewController {

   fileprivate let scrollView: UIScrollView = UIScrollView()
   fileprivate let linearView: UIView = UIView()
   fileprivate let materialStandardView: UIView = UIView()
   fileprivate let materialDecelerationView: UIView = UIView()
   fileprivate let materialAccelerationView: UIView = UIView()
   fileprivate let materialSharpView: UIView = UIView()

   override func viewDidLoad() {
      super.viewDidLoad()

      view.backgroundColor = .white
      title = "Animation Timing"
      setupExampleViews()
   }


   override func viewDidAppear(_ animated: Bool) {
      super.viewDidAppear(animated)
      let timeInterval: TimeInterval = 2 * (Constants.AnimationTime.interval + Constants.AnimationTime.delay)
      var _: Timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(self.playAnimations), userInfo: nil, repeats: true)
      playAnimations()

   }

   @objc func playAnimations() {
      let linearCurve: CAMediaTimingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
      applyAnimation(toView: linearView, withTimingFunction: linearCurve)

      if let materialStandard = CAMediaTimingFunction.mdc_function(withType: .standard) {
         applyAnimation(toView: materialStandardView, withTimingFunction: materialStandard)
      } else {
         materialStandardView.removeFromSuperview()
      }

      if let materialDeceleration = CAMediaTimingFunction.mdc_function(withType: .deceleration) {
         applyAnimation(toView: materialDecelerationView, withTimingFunction: materialDeceleration)
      } else {
         materialDecelerationView.removeFromSuperview()
      }

      if let materialAcceleration = CAMediaTimingFunction.mdc_function(withType: .acceleration) {
         applyAnimation(toView: materialAccelerationView, withTimingFunction: materialAcceleration)
      } else {
         materialAccelerationView.removeFromSuperview()
      }
    
      if let materialSharp = CAMediaTimingFunction.mdc_function(withType: .sharp) {
         applyAnimation(toView: materialSharpView, withTimingFunction: materialSharp)
      } else {
         materialSharpView.removeFromSuperview()
      }
   }

   func applyAnimation(toView view: UIView, withTimingFunction timingFunction : CAMediaTimingFunction) {
      let animWidth: CGFloat = self.view.frame.size.width - view.frame.size.width - 32.0
      let transform: CGAffineTransform = CGAffineTransform.init(translationX: animWidth, y: 0)
      UIView.mdc_animate(with: timingFunction, duration: Constants.AnimationTime.interval, delay: Constants.AnimationTime.delay, options: [], animations: {
         view.transform = transform
      }, completion: { Bool in
         UIView.mdc_animate(with: timingFunction, duration: Constants.AnimationTime.interval, delay: Constants.AnimationTime.delay, options: [], animations: {
            view.transform = CGAffineTransform.identity
         }, completion: nil)
      })
   }
}

extension AnimationTimingSwiftExampleViewController {
   fileprivate func setupExampleViews() {

      let curveLabel: (String) -> UILabel = { labelTitle in
         let label: UILabel = UILabel()
         label.text = labelTitle
         label.font = MDCTypography.captionFont()
         label.textColor = UIColor(white: 0, alpha: MDCTypography.body2FontOpacity())
         label.sizeToFit()
         return label
      }

      let defaultColors: [UIColor] = [UIColor.darkGray.withAlphaComponent(0.95),
                                      UIColor.darkGray.withAlphaComponent(0.90),
                                      UIColor.darkGray.withAlphaComponent(0.85),
                                      UIColor.darkGray.withAlphaComponent(0.80),
                                      UIColor.darkGray.withAlphaComponent(0.75)]

      scrollView.frame = view.bounds
      scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
      scrollView.contentSize = CGSize(width: view.frame.width,
                                      height: view.frame.height + Constants.Sizes.topMargin)
      scrollView.clipsToBounds = true
      view.addSubview(scrollView)

      let lineSpace: CGFloat = (view.frame.size.height - 50.0) / 5.0
      let linearLabel: UILabel = curveLabel("Linear")
      linearLabel.frame = CGRect(x: Constants.Sizes.leftGutter, y: Constants.Sizes.topMargin, width: linearLabel.frame.size.width, height: linearLabel.frame.size.height)
      scrollView.addSubview(linearLabel)

      let linearViewFrame: CGRect = CGRect(x: Constants.Sizes.leftGutter, y: Constants.Sizes.leftGutter + Constants.Sizes.topMargin, width: Constants.Sizes.circleSize.width, height: Constants.Sizes.circleSize.height)
      linearView.frame = linearViewFrame
      linearView.backgroundColor = defaultColors[0]
      linearView.layer.cornerRadius = Constants.Sizes.circleSize.width / 2.0
      scrollView.addSubview(linearView)

      let materialEaseInOutLabel: UILabel = curveLabel("MDCAnimationTimingFunctionStandard")
      materialEaseInOutLabel.frame = CGRect(x: Constants.Sizes.leftGutter, y: lineSpace, width: materialEaseInOutLabel.frame.size.width, height: materialEaseInOutLabel.frame.size.height)
      scrollView.addSubview(materialEaseInOutLabel)

      let materialEaseInOutViewFrame: CGRect = CGRect(x: Constants.Sizes.leftGutter, y: lineSpace + Constants.Sizes.textOffset, width: Constants.Sizes.circleSize.width, height: Constants.Sizes.circleSize.height)
      materialStandardView.frame = materialEaseInOutViewFrame
      materialStandardView.backgroundColor = defaultColors[1]
      materialStandardView.layer.cornerRadius = Constants.Sizes.circleSize.width / 2.0
      scrollView.addSubview(materialStandardView)

      let materialEaseOutLabel: UILabel = curveLabel("MDCAnimationTimingFunctionDeceleration")
      materialEaseOutLabel.frame = CGRect(x: Constants.Sizes.leftGutter, y: lineSpace * 2.0, width: materialEaseOutLabel.frame.size.width, height: materialEaseOutLabel.frame.size.height)
      scrollView.addSubview(materialEaseOutLabel)

      let materialEaseOutViewFrame: CGRect = CGRect(x: Constants.Sizes.leftGutter, y: lineSpace * 2.0 + Constants.Sizes.textOffset, width: Constants.Sizes.circleSize.width, height: Constants.Sizes.circleSize.height)
      materialDecelerationView.frame = materialEaseOutViewFrame
      materialDecelerationView.backgroundColor = defaultColors[2]
      materialDecelerationView.layer.cornerRadius = Constants.Sizes.circleSize.width / 2.0
      scrollView.addSubview(materialDecelerationView)

      let materialEaseInLabel: UILabel = curveLabel("MDCAnimationTimingFunctionAcceleration")
      materialEaseInLabel.frame = CGRect(x: Constants.Sizes.leftGutter, y: lineSpace * 3.0, width: materialEaseInLabel.frame.size.width, height: materialEaseInLabel.frame.size.height)
      scrollView.addSubview(materialEaseInLabel)

      let materialEaseInViewFrame: CGRect = CGRect(x: Constants.Sizes.leftGutter, y: lineSpace * 3.0 + Constants.Sizes.textOffset, width: Constants.Sizes.circleSize.width, height: Constants.Sizes.circleSize.height)
      materialAccelerationView.frame = materialEaseInViewFrame
      materialAccelerationView.backgroundColor = defaultColors[3]
      materialAccelerationView.layer.cornerRadius = Constants.Sizes.circleSize.width / 2.0
      scrollView.addSubview(materialAccelerationView)
    
      let materialSharpLabel: UILabel = curveLabel("MDCAnimationTimingSharp")
      materialSharpLabel.frame = CGRect(x: Constants.Sizes.leftGutter, y: lineSpace * 4.0, width: materialSharpLabel.frame.size.width, height: materialSharpLabel.frame.size.height)
      scrollView.addSubview(materialSharpLabel)
      
      let materialSharpViewFrame: CGRect = CGRect(x: Constants.Sizes.leftGutter, y: lineSpace * 4.0 +
         Constants.Sizes.textOffset, width: Constants.Sizes.circleSize.width, height: Constants.Sizes.circleSize.height)
      materialSharpView.frame = materialSharpViewFrame
      materialSharpView.backgroundColor = defaultColors[4]
      materialSharpView.layer.cornerRadius = Constants.Sizes.circleSize.width / 2.0
      scrollView.addSubview(materialSharpView)
   }

  @objc class func catalogMetadata() -> [String: Any] {
    return [
      "breadcrumbs": ["Animation Timing", "Animation Timing (Swift)"],
      "primaryDemo": false,
      "presentable": false,
      "skip_snapshots": true, // The automatic animations cause the snapshot tests to hang.
    ]
  }

}
